#include <string.h>
#include <iostream>
using std::cout;
using std::endl;

class String{
public:
    String()
    :_pstr(new char[1]())
    {
        cout << "String()" << endl;
    }
    //explicit 禁止隐式类型转换
    String(const char * pstr)
    :_pstr(new char[strlen(pstr) + 1]())
    {
        strcpy(_pstr, pstr);
        cout << "String(const char *)" << endl;
    }
    String(const String & rhs)
    :_pstr(new char[strlen(rhs._pstr) + 1]())
    {
        strcpy(_pstr, rhs._pstr);
        cout << "String(const String &)" << endl;
    }

    //四步走：
    //1.自赋值判断
    //2.先回收左操作数申请的堆空间
    //3.进行深拷贝
    //4.返回当前对象
    String & operator=(const String & rhs){
        cout << "operator=(const String &)" << endl;
        if(this != &rhs){
            delete [] _pstr;
            _pstr = new char[strlen(rhs._pstr) + 1]();
            strcpy(_pstr, rhs._pstr);
        }
        return *this;
    }
    bool empty() const{
        return size() == 0;
    }
    int size() const{
        return strlen(_pstr);
    }
    const char * c_str() const{
        return _pstr;
    }
    ~String(){
        if(_pstr){
            delete [] _pstr;
            _pstr = nullptr;
        }
        cout << "~String()" << endl;
    }
    //s1.append(s2);
    //先申请一个临时空间，长度要求能够容纳s1+s2
    //分别把s1和s2复制过来
    //s1的指针再去指向这个新的
    String & append(const String & rhs){
        //先申请一个临时的空间，足够容纳s1和s2的字符串拼接
        char * temp = new char[strlen(_pstr) + strlen(rhs._pstr) + 1]();
        //处理字符串的复制操作
        strcpy(temp, _pstr);
        strcat(temp, rhs._pstr);
        //先去释放左操作数对象原先申请的堆空间
        delete [] _pstr;
        _pstr = temp;
        return *this;
    }
    //const引用可以取绑定右值，临时对象
    //可以提升右值的生命周期
    String & append(const char * pstr){
        return append(String(pstr));
    }

private:
    char * _pstr;
};


void test(){
    String s1;
    String s2("hello");
    //cout << s1 << endl;
    //cout << s2 << endl;
    cout << "================" << endl;
    String s3 = "world";

    String s4 = s3;
    
}

void test2(){
    String s1 = "hello";
    String s2 = "world";
    cout << s1.c_str() << ":" << s2.c_str() << endl;
    s1 = s2;
    cout << s1.c_str() << ":" << s2.c_str() << endl;
    cout << s1.empty() << endl;
    cout << s1.size() << endl;
}

void test3(){
    String s1 = "hello";
    String s2 = "world";
    s1.append(s2);
    cout << s1.c_str() << endl;

    String s3 = "hello";
    s3.append("c++");
    cout << s3.c_str() << endl;
}

int main()
{
    test3();
    return 0;
}

